//
//  UIView+RBLayout.m
//  zhongzhenglu
//
//  Created by XL on 2022/7/11.
//

#import "UIView+RBLayout.h"
#import "Masonry.h"
#import <objc/objc.h>
#import <objc/runtime.h>

static char *const RB_BOTTOM_CONS_KEY_V = "RB_BOTTOM_CONS_KEY_V";
static char *const RB_TOP_CONS_KEY_V = "RB_TOP_CONS_KEY_V";
static char *const RB_VIEWS_ARRAY_KEY_V = "RB_VIEWS_ARRAY_KEY_V";
static char *const RB_WIDTH_CONS_KEY_V = "RB_WIDTH_CONS_KEY_V";
static char *const RB_HEIGHT_CONS_KEY_V = "RB_HEIGHT_CONS_KEY_V";

static char *const RB_RIGHT_CONS_KEY_V_H = "RB_RIGHT_CONS_KEY_V_H";
static char *const RB_LEFT_CONS_KEY_V_H = "RB_LEFT_CONS_KEY_V_H";
static char *const RB_VIEWS_ARRAY_KEY_V_H = "RB_VIEWS_ARRAY_KEY_V_H";
static char *const RB_WIDTH_CONS_KEY_V_H = "RB_WIDTH_CONS_KEY_V_H";
static char *const RB_HEIGHT_CONS_KEY_V_H = "RB_HEIGHT_CONS_KEY_V_H";

@implementation UIView(RBLayout)

#pragma mark - Private

- (void)view_setLastBottomCons: (MASConstraint *)cons
{
    [self view_setBottomCons:cons forView:self];
}

- (MASConstraint *)view_getLastBottomCons
{
    return [self view_getBottomConsForView:self];
}

- (void)view_setBottomCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_BOTTOM_CONS_KEY_V, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)view_getBottomConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_BOTTOM_CONS_KEY_V);
}

- (void)view_setTopCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_TOP_CONS_KEY_V, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)view_getTopConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_TOP_CONS_KEY_V);
}

- (void)view_setWidthCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_WIDTH_CONS_KEY_V, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)view_getWidthConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_WIDTH_CONS_KEY_V);
}

- (void)view_setHeightCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_HEIGHT_CONS_KEY_V, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)view_getHeightConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_HEIGHT_CONS_KEY_V);
}

- (NSMutableArray *)view_getViewsArray
{
    NSMutableArray *arrayM = objc_getAssociatedObject(self, RB_VIEWS_ARRAY_KEY_V);
    if (!arrayM)
    {
        arrayM = [NSMutableArray array];
        objc_setAssociatedObject(self, RB_VIEWS_ARRAY_KEY_V, arrayM, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return arrayM;
}

#pragma mark - Public

- (void)view_clear
{
    NSMutableArray *mySubViews = [self view_getViewsArray];
    for (NSInteger i = mySubViews.count - 1; i >= 0; i--)
    {
        UIView *subView = mySubViews[i];
        [[self view_getWidthConsForView:subView] uninstall];
        [[self view_getHeightConsForView:subView] uninstall];
        [subView removeFromSuperview];
    }
    [self view_setLastBottomCons:nil];
    [mySubViews removeAllObjects];
}

- (void)view_addView: (UIView *)view
     withHeight: (CGFloat)height
          width: (CGFloat)width
            top: (CGFloat)top
         bottom: (CGFloat)bottom
           left: (CGFloat)left
          right: (CGFloat)right
        centerX:(BOOL)centerX
{
    NSMutableArray *mySubViews = [self view_getViewsArray];
    if (!mySubViews.count)
    {
        UIView *stick = [UIView new];
        [mySubViews addObject:stick];
        stick.backgroundColor = [UIColor clearColor];
        [self addSubview:stick];
        [stick mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.mas_equalTo(0);
            make.left.right.mas_equalTo(0);
            make.height.mas_equalTo(0.1);
            MASConstraint *bottomCons = make.bottom.mas_equalTo(0);
            [self view_setLastBottomCons:bottomCons];
            [self view_setBottomCons:bottomCons forView:stick];
        }];
    }
    [self view_insertView:view beforeView:nil afterView:nil withHeight:height width:width top:top bottom:bottom left:left right:right centerX:centerX];
}

- (void)view_insertView: (UIView *)view
        beforeView: (UIView *)beforeView
         afterView: (UIView *)afterView
        withHeight: (CGFloat)height
             width: (CGFloat)width
               top: (CGFloat)top
            bottom: (CGFloat)bottom
              left: (CGFloat)left
             right: (CGFloat)right
           centerX: (BOOL)centerX
{
    if (!view)
    {
        return;
    }
    
    NSMutableArray *mySubViews = [self view_getViewsArray];
    if (!mySubViews.count)
    {
        //没调用 rbSetContentWidth: 不执行
        return;
    }
    
    if (afterView == mySubViews.lastObject)
    {
        afterView = nil;
    }
    
    //加view
    [self addSubview:view];
    
    //修改约束
    if (beforeView)
    {
        if (![mySubViews containsObject:beforeView])
        {
            return;
        }
        
        NSInteger index = [mySubViews indexOfObject:beforeView];
        UIView *theBeforeView = mySubViews[index - 1];
        UIView *theAfterView = beforeView;
        [mySubViews insertObject:view atIndex:index];
        
        MASConstraint *bottomCons = [self view_getBottomConsForView:theBeforeView];
        [bottomCons uninstall];
        MASConstraint *topCons = [self view_getTopConsForView:theAfterView];
        [topCons uninstall];
        
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *topCons = make.top.mas_equalTo(theBeforeView.mas_bottom).offset(top);
            [self view_setTopCons:topCons forView:view];
        }];
        if (bottom != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                MASConstraint *bottomCons = make.bottom.mas_equalTo(theAfterView.mas_top).offset(-bottom);
                [self view_setBottomCons:bottomCons forView:view];
            }];
        }
    }
    else if(afterView)
    {
        if (![mySubViews containsObject:afterView])
        {
            return;
        }
        
        NSInteger index = [mySubViews indexOfObject:afterView];
        UIView *theBeforeView = afterView;
        UIView *theAfterView = mySubViews[index + 1];
        [mySubViews insertObject:view atIndex:index + 1];
        
        MASConstraint *bottomCons = [self view_getBottomConsForView:theBeforeView];
        [bottomCons uninstall];
        MASConstraint *topCons = [self view_getTopConsForView:theAfterView];
        [topCons uninstall];
        
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *topCons = make.top.mas_equalTo(theBeforeView.mas_bottom).offset(top);
            [self view_setTopCons:topCons forView:view];
        }];
        if (bottom != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                MASConstraint *bottomCons = make.bottom.mas_equalTo(theAfterView.mas_top).offset(-bottom);
                [self view_setBottomCons:bottomCons forView:view];
            }];
        }
    }
    else
    {
        //获取上一个view
        UIView *lastView = mySubViews.lastObject;
        [mySubViews addObject:view];
        MASConstraint *bottomCons = [self view_getLastBottomCons];
        [bottomCons uninstall];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *topCons = make.top.mas_equalTo(lastView.mas_bottom).offset(top);
            [self view_setTopCons:topCons forView:view];
        }];
        if (bottom != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                MASConstraint *bottomCons = make.bottom.mas_equalTo(-bottom);
                [self view_setLastBottomCons:bottomCons];
                [self view_setBottomCons:bottomCons forView:view];
            }];
        }
    }
    
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        if (height != CGFLOAT_MIN)
        {
            MASConstraint *heightCons = make.height.mas_equalTo(height);
            [self view_setHeightCons:heightCons forView:view];
        }
    }];
    
    if (width != CGFLOAT_MIN)
    {
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *widthCons = make.width.mas_equalTo(width);
            [self view_setWidthCons:widthCons forView:view];
        }];
        if (centerX)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.centerX.mas_equalTo(0);
            }];
        }
        else if(left != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.left.mas_equalTo(left);
            }];
        }
        else if(right != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.right.mas_equalTo(-right);
            }];
        }
    }
    else
    {
        if (centerX)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.centerX.mas_equalTo(0);
            }];
        }
        else
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                if (left != CGFLOAT_MIN)
                {
                    make.left.mas_equalTo(left);
                }
                if (right != CGFLOAT_MIN)
                {
                    make.right.mas_equalTo(-right);
                }
            }];
        }
    }
}

- (void)view_removeView: (UIView *)view withPadding:(CGFloat)padding
{
    if (!view)
    {
        return;
    }
    
    NSMutableArray *mySubViews = [self view_getViewsArray];
    if (![mySubViews containsObject:view])
    {
        return;
    }
    if (!mySubViews.count)
    {
        //没调用 rbSetContentWidth: 不执行
        return;
    }
    NSInteger index = [mySubViews indexOfObject:view];
    UIView *beforeView = mySubViews[index - 1];
    if (index == mySubViews.count - 1)
    {
        [[self view_getBottomConsForView:beforeView] uninstall];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.bottom.mas_equalTo(-padding);
        }];
        
        [beforeView mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *bottomCons = make.bottom.mas_equalTo(-padding);
            [self view_setLastBottomCons:bottomCons];
            [self view_setBottomCons:bottomCons forView:beforeView];
        }];
    }
    else
    {
        [[self view_getBottomConsForView:beforeView] uninstall];
        UIView *afterView = mySubViews[index + 1];
        [[self view_getTopConsForView:afterView] uninstall];
        
        [beforeView mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *bottomCons = make.bottom.mas_equalTo(afterView.mas_top).offset(-padding);
            [self view_setBottomCons:bottomCons forView:beforeView];
        }];
        
        [afterView mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *topCons = make.top.mas_equalTo(beforeView.mas_bottom).offset(padding);
            [self view_setTopCons:topCons forView:afterView];
        }];
    }
    
    [mySubViews removeObject:view];
    [view removeFromSuperview];
}

@end


@implementation UIView(RBLayoutHorizontal)

#pragma mark - Private

- (void)h_view_setLastRightCons: (MASConstraint *)cons
{
    [self h_view_setRightCons:cons forView:self];
}

- (MASConstraint *)h_view_getLastRightCons
{
    return [self h_view_getRightConsForView:self];
}

- (void)h_view_setRightCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_RIGHT_CONS_KEY_V_H, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)h_view_getRightConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_RIGHT_CONS_KEY_V_H);
}

- (void)h_view_setLeftCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_LEFT_CONS_KEY_V_H, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)h_view_getLeftConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_LEFT_CONS_KEY_V_H);
}

- (void)h_view_setWidthCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_WIDTH_CONS_KEY_V_H, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)h_view_getWidthConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_WIDTH_CONS_KEY_V_H);
}

- (void)h_view_setHeightCons: (MASConstraint *)cons forView: (UIView *)view
{
    objc_setAssociatedObject(view, RB_HEIGHT_CONS_KEY_V_H, cons, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (MASConstraint *)h_view_getHeightConsForView: (UIView *)view
{
    return objc_getAssociatedObject(view, RB_HEIGHT_CONS_KEY_V_H);
}

- (NSMutableArray *)h_view_getViewsArray
{
    NSMutableArray *arrayM = objc_getAssociatedObject(self, RB_VIEWS_ARRAY_KEY_V_H);
    if (!arrayM)
    {
        arrayM = [NSMutableArray array];
        objc_setAssociatedObject(self, RB_VIEWS_ARRAY_KEY_V_H, arrayM, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return arrayM;
}

#pragma mark - Public

- (void)h_view_clear
{
    NSMutableArray *mySubViews = [self h_view_getViewsArray];
    for (NSInteger i = mySubViews.count - 1; i >= 0; i--)
    {
        UIView *subView = mySubViews[i];
        [[self h_view_getWidthConsForView:subView] uninstall];
        [[self h_view_getHeightConsForView:subView] uninstall];
        [subView removeFromSuperview];
    }
    [self h_view_setLastRightCons:nil];
    [mySubViews removeAllObjects];
}

- (void)h_view_addView: (UIView *)view
            withHeight: (CGFloat)height
                 width: (CGFloat)width
                   top: (CGFloat)top
                bottom: (CGFloat)bottom
                  left: (CGFloat)left
                 right: (CGFloat)right
               centerY: (BOOL)centerY{
    NSMutableArray *mySubViews = [self h_view_getViewsArray];
    if (!mySubViews.count)
    {
        UIView *stick = [UIView new];
        [mySubViews addObject:stick];
        stick.backgroundColor = [UIColor clearColor];
        [self addSubview:stick];
        [stick mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.bottom.mas_equalTo(0);
            make.left.mas_equalTo(0);
            make.width.mas_equalTo(0.1);
            MASConstraint *rightCons = make.right.mas_equalTo(0);
            [self h_view_setLastRightCons:rightCons];
            [self h_view_setRightCons:rightCons forView:stick];
        }];
    }
    [self h_view_insertView:view beforeView:nil afterView:nil withHeight:height width:width top:top bottom:bottom left:left right:right centerY:centerY];
}

- (void)h_view_insertView: (UIView *)view
               beforeView: (UIView *)beforeView
                afterView: (UIView *)afterView
               withHeight: (CGFloat)height
                    width: (CGFloat)width
                      top: (CGFloat)top
                   bottom: (CGFloat)bottom
                     left: (CGFloat)left
                    right: (CGFloat)right
                  centerY: (BOOL)centerY
{
    if (!view)
    {
        return;
    }
    
    NSMutableArray *mySubViews = [self h_view_getViewsArray];
    if (!mySubViews.count)
    {
        //没调用 rbSetContentWidth: 不执行
        return;
    }
    
    if (afterView == mySubViews.lastObject)
    {
        afterView = nil;
    }
    
    //加view
    [self addSubview:view];
    
    //修改约束
    if (beforeView)
    {
        if (![mySubViews containsObject:beforeView])
        {
            return;
        }
        
        NSInteger index = [mySubViews indexOfObject:beforeView];
        UIView *theBeforeView = mySubViews[index - 1];
        UIView *theAfterView = beforeView;
        [mySubViews insertObject:view atIndex:index];
        
        MASConstraint *rightCons = [self h_view_getRightConsForView:theBeforeView];
        [rightCons uninstall];
        MASConstraint *leftCons = [self h_view_getLeftConsForView:theAfterView];
        [leftCons uninstall];
        
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *leftCons = make.left.mas_equalTo(theBeforeView.mas_right).offset(left);
            [self h_view_setLeftCons:leftCons forView:view];
        }];
        if (right != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                MASConstraint *rightCons = make.right.mas_equalTo(theAfterView.mas_left).offset(-left);
                [self h_view_setRightCons:rightCons forView:view];
            }];
        }
    }
    else if(afterView)
    {
        if (![mySubViews containsObject:afterView])
        {
            return;
        }
        
        NSInteger index = [mySubViews indexOfObject:afterView];
        UIView *theBeforeView = afterView;
        UIView *theAfterView = mySubViews[index + 1];
        [mySubViews insertObject:view atIndex:index + 1];
        
        MASConstraint *rightCons = [self h_view_getRightConsForView:theBeforeView];
        [rightCons uninstall];
        MASConstraint *leftCons = [self h_view_getLeftConsForView:theAfterView];
        [leftCons uninstall];
        
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *leftCons = make.left.mas_equalTo(theBeforeView.mas_right).offset(left);
            [self h_view_setLeftCons:leftCons forView:view];
        }];
        if (right != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                MASConstraint *rightCons = make.right.mas_equalTo(theAfterView.mas_left).offset(-right);
                [self h_view_setRightCons:rightCons forView:view];
            }];
        }
    }
    else
    {
        //获取上一个view
        UIView *lastView = mySubViews.lastObject;
        [mySubViews addObject:view];
        MASConstraint *rightCons = [self h_view_getLastRightCons];
        [rightCons uninstall];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *leftCons = make.left.mas_equalTo(lastView.mas_right).offset(left);
            [self h_view_setLeftCons:leftCons forView:view];
        }];
        if (right != CGFLOAT_MIN)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                MASConstraint *rightCons = make.right.mas_equalTo(-right);
                [self h_view_setLastRightCons:rightCons];
                [self h_view_setRightCons:rightCons forView:view];
            }];
        }
    }
    
    [view mas_makeConstraints:^(MASConstraintMaker *make) {
        if (width != CGFLOAT_MIN)
        {
            MASConstraint *widthCons = make.width.mas_equalTo(width);
            [self h_view_setWidthCons:widthCons forView:view];
        }
    }];
    
    if (height != CGFLOAT_MIN)
    {
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *heightCons = make.height.mas_equalTo(height);
            [self h_view_setHeightCons:heightCons forView:view];
        }];
        if (centerY)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.centerY.mas_equalTo(0);
            }];
        }
        else
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                if (top != CGFLOAT_MIN)
                {
                    make.top.mas_equalTo(top);
                }
                if (bottom != CGFLOAT_MIN)
                {
                    make.bottom.mas_equalTo(-bottom);
                }
            }];
        }
    }
    else
    {
        if (centerY)
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                make.centerY.mas_equalTo(0);
            }];
        }
        else
        {
            [view mas_makeConstraints:^(MASConstraintMaker *make) {
                if (top != CGFLOAT_MIN)
                {
                    make.top.mas_equalTo(top);
                }
                if (bottom != CGFLOAT_MIN)
                {
                    make.bottom.mas_equalTo(-bottom);
                }
            }];
        }
    }
}

- (void)h_view_removeView: (UIView *)view withPadding: (CGFloat)padding
{
    if (!view)
    {
        return;
    }
    
    NSMutableArray *mySubViews = [self h_view_getViewsArray];
    if (![mySubViews containsObject:view])
    {
        return;
    }
    if (!mySubViews.count)
    {
        //没调用 rbSetContentWidth: 不执行
        return;
    }
    NSInteger index = [mySubViews indexOfObject:view];
    UIView *beforeView = mySubViews[index - 1];
    if (index == mySubViews.count - 1)
    {
        [[self h_view_getRightConsForView:beforeView] uninstall];
        [view mas_makeConstraints:^(MASConstraintMaker *make) {
            make.bottom.mas_equalTo(-padding);
        }];
        
        [beforeView mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *rightCons = make.right.mas_equalTo(-padding);
            [self h_view_setLastRightCons:rightCons];
            [self h_view_setRightCons:rightCons forView:view];
        }];
    }
    else
    {
        [[self h_view_getRightConsForView:beforeView] uninstall];
        UIView *afterView = mySubViews[index + 1];
        [[self h_view_getLeftConsForView:afterView] uninstall];
        
        [beforeView mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *rightCons = make.right.mas_equalTo(afterView.mas_left).offset(-padding);
            [self h_view_setRightCons:rightCons forView:beforeView];
        }];
        
        [afterView mas_makeConstraints:^(MASConstraintMaker *make) {
            MASConstraint *leftCons = make.left.mas_equalTo(beforeView.mas_right).offset(padding);
            [self h_view_setLeftCons:leftCons forView:afterView];
        }];
    }
    
    [mySubViews removeObject:view];
    [view removeFromSuperview];
}

@end
